package com.zdxlz.fcmp.common.security.util;

import com.zdxlz.fcmp.common.core.constant.CommonConstants;
import com.zdxlz.fcmp.common.core.constant.enums.ResCode;
import com.zdxlz.fcmp.common.core.exception.BizException;
import com.zdxlz.fcmp.common.security.config.JwtConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * @className JwtTokenUtil
 * @description
 * @author: aman
 * @date 2025/1/30 18:45
 */
@Component
@Data
@AllArgsConstructor
public class JwtTokenUtil {

    private final JwtConfig jwtConfig;

    // 生成 JWT
    public String generateAccessToken(String mobile, Long version) {
        SecretKey key = Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes());
        return Jwts.builder()
                .subject(mobile)
                .claim(CommonConstants.VERSION, version)
                .issuedAt(new Date())
                .expiration(new Date(System.currentTimeMillis() + 1000 * jwtConfig.getAccessTokenExpiration()))
                .signWith(key)
                .compact();
    }

    public String generateRefreshToken(String mobile, Long version) {
        SecretKey key = Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes());
        return Jwts.builder()
                .subject(mobile)
                .claim(CommonConstants.VERSION, version)
                .issuedAt(new Date())
                .expiration(new Date(System.currentTimeMillis() + 1000 * jwtConfig.getRefreshTokenExpiration()))
                .signWith(key)
                .compact();
    }


    // 获取subject信息
    public String parseToken(String token) {
        SecretKey key = Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes());

        try {
            return Jwts.parser()
                    .verifyWith(key)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload()
                    .getSubject();
        } catch (ExpiredJwtException e) {
            throw new BizException(ResCode.ERR_AUTH_EXPIRE.getCode(), ResCode.ERR_AUTH_EXPIRE.getReason());
        }

    }

    // 获取version信息
    public Claims getClaims(String token) {
        SecretKey key = Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes());

        try {
            return Jwts.parser()
                    .verifyWith(key)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (ExpiredJwtException e) {
            throw new BizException(ResCode.ERR_AUTH_EXPIRE.getCode(), ResCode.ERR_AUTH_EXPIRE.getReason());
        }
    }


    /**
     * 判断token是否过期
     *
     * @param token
     * @return true:过期，false:未过期
     */
    public boolean isTokenExpired(String token) {
        SecretKey key = Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes());
        try {
            return Jwts.parser()
                    .verifyWith(key)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload()
                    .getExpiration()
                    .before(new Date());
        } catch (ExpiredJwtException e) {
            throw new BizException(ResCode.ERR_AUTH_EXPIRE.getCode(), ResCode.ERR_AUTH_EXPIRE.getReason());
        }
    }

    // 解析 token
    public boolean validateToken(String token, String username) {
        return (!isTokenExpired(token) && username.equals(parseToken(token)));
    }


    // 用于提取 token 的签名部分
    public static String getSignature(String token) {
        String[] splitToken = token.split("\\.");  // JWT 是由三部分组成的，分隔符是 '.'
        if (splitToken.length != 3) {
            throw new IllegalArgumentException("Invalid JWT token format");
        }
        return splitToken[2];  // 返回签名部分（第三部分）
    }

}
